4.6 Навигация. Передача данных. TextField
2 из 2 шагов пройдено

 Навигация. Передача данных. TextField

➡️Ссылка на репозиторий с кодом этого урока

Возвращение данных на предыдущий экран

В Flutter существует несколько способов передать данные обратно на предыдущий экран при навигации. Самый простой и распространенный способ — вернуть данные через Navigator.pop()

Файл first_screen.dart

import 'package:flutter/material.dart';  
import 'package:flutter_navigation/screens/second_screen.dart';  
import 'package:flutter_navigation/screens/user.dart';  
  
class FirstScreen extends StatefulWidget {  
  static const routeName = '/first';  
  
  const FirstScreen({super.key});  
  
  @override  
  State<FirstScreen> createState() => _FirstScreenState();  
}  
  
class _FirstScreenState extends State<FirstScreen> {  
  TextEditingController textController = TextEditingController();  
  @override  
  Widget build(BuildContext context) {  
    final data = ModalRoute.of(context)?.settings.arguments as UserProfile;  
  
    return Scaffold(  
      appBar: AppBar(  
        title: const Text('Первый экран'),  
        backgroundColor: Colors.green[300],  
      ),  
      body: Container(  
        decoration: BoxDecoration(  
          gradient: LinearGradient(  
            colors: [Color(0xFFBFF098), Color(0xFF6FD6FF)],  
            begin: Alignment.topLeft,  
            end: Alignment.bottomRight,  
          ),  
        ),  
        child: SizedBox(  
          width: double.infinity,  
          child: Column(  
            mainAxisAlignment: MainAxisAlignment.center,  
            children: [  
              Text(data.name ?? ''),  
  
              Padding(  
                padding: const EdgeInsets.all(24.0),  
                child: TextField(  
                  controller: textController,  
                  decoration: const InputDecoration(  
                    border: OutlineInputBorder(),  
                    labelText: 'Введите сообщение',  
                  ),  
                ),  
              ),  
  
              ElevatedButton(  
                onPressed:  
                    () => Navigator.pushNamed(  
                      context,  
                      SecondScreen.routeName,  
                      arguments: UserProfile(  
                        name: data.name,  
                        message: textController.text,  
                      ),  
                    ),  
                child: const Text("Открыть 2й экран"),  
              ),  
              ElevatedButton(  
                onPressed: () => Navigator.pop(
	                context, 
	                "Ты был на 1 экране! 
	                Я запомнил твое имя: ${data.name}"
	            ),  
                child: const Text("Вернуться Назад"),  
              ),  
            ],  
          ),  
        ),  
      ),  
    );  
  }  
}

В код экрана мы добавили в обработчик нажатия кнопки Вернуться Назад этот код:

ElevatedButton(  
  onPressed: () => Navigator.pop(
    context, 
    "Ты был на 1 экране! Я запомнил твое имя: ${data.name}"
  ),  
  child: const Text("Вернуться Назад"),  
), 

Через pop() можно вернуть любой тип данных:

  • Примитивы (Stringintbool)
  • Списки и словари (ListMap)
  • Пользовательские объекты (свои классы)
  • Null (если ничего не передать в pop)

Теперь чтобы принять значения на экране MainScreen нужно использовать методы Navigator.push() и Navigator.pushNamed(), которые могут возвращать значения.

Метод pushNamed() возвращает Future<T>, где T — это тип данных, который будет возвращен при вызове Navigator.pop() со второго экрана.

Нужно будет написать примерно такое

ElevatedButton(  
  onPressed: () async {  
    final result = await Navigator.pushNamed(  
      context,  
      FirstScreen.routeName,  
      arguments: UserProfile(name: textController.text),  
    );
  }
),

Что такое await и async и зачем он нужен?

await — это часть асинхронного программирования в Dart. Он используется для ожидания завершения асинхронных операций, которые возвращают Future. Работает обычно в паре с методом async (помечаем функцию которая будет работать асинхронно)

Здесь код делает следующее:

  1. Открывает экран FirstScreen
  2. Приостанавливает выполнение текущей функции до тех пор, пока пользователь не вернётся с экрана FirstScreen (вызовет Navigator.pop())
  3. Когда пользователь возвращается, в переменную result сохраняется значение, переданное в Navigator.pop()

Без await код продолжит выполняться сразу, не дожидаясь возврата пользователя, и вы не сможете сразу получить результат.

  • Не забываем создать переменную состояния String? resultMessage у неё тип данных опциональный потому что неизвестно заранее какой тип данных вернёт метод Navigator.pushNamed это будет в будущем или null или String
  • Функция обработчик нажатия теперь async потому что внутри используется await
  • Не забываем обновить состояние resultMessage через setState
  • Нужно вывести возвращаемый результат, обязательно делаем проверку на null

Файл main_screen.dart

import 'package:flutter/material.dart';  
import 'package:flutter_navigation/screens/first_screen.dart';  
import 'package:flutter_navigation/screens/user.dart';  
  
class MainScreen extends StatefulWidget {  
  static const routeName = '/main';  
  
  const MainScreen({super.key});  
  
  @override  
  State<MainScreen> createState() => _MainScreenState();  
}  
  
class _MainScreenState extends State<MainScreen> {  
  TextEditingController textController = TextEditingController();  
  
  String? resultMessage; // Добавляем переменную для хранения результата  
  
  @override  
  Widget build(BuildContext context) {  
    return Scaffold(  
      appBar: AppBar(title: const Text('Главный экран'), centerTitle: true),  
      backgroundColor: Colors.white,  
      body: SizedBox(  
        width: double.infinity,  
        child: Column(  
          mainAxisAlignment: MainAxisAlignment.center,  
          children: [  
            Padding(  
              padding: const EdgeInsets.all(24.0),  
              child: TextField(  
                controller: textController,  
                decoration: const InputDecoration(  
                  border: OutlineInputBorder(),  
                  labelText: 'Введите имя',  
                ),  
              ),  
            ),  
  
            // Показываем результат, если он есть  
            if (resultMessage != null)  
              Padding(  
                padding: const EdgeInsets.all(16.0),  
                child: Text(  
                  resultMessage ?? "",  
                  style: TextStyle(  
                    fontSize: 16,  
                    fontWeight: FontWeight.bold,  
                    color: Colors.green,  
                  ),  
                ),  
              ),  
  
            ElevatedButton(  
              onPressed: () async {  
                // Добавляем await и обрабатываем результат  
                final result = await Navigator.pushNamed(  
                  context,  
                  FirstScreen.routeName,  
                  arguments: UserProfile(name: textController.text),  
                );  
  
                // Обновляем состояние с полученным результатом  
                if (result != null) {  
                  setState(() {  
                    resultMessage = result as String;  
                  });  
                }  
              },  
              child: const Text("Открыть FirstScreen"),  
            ),  
          ],  
        ),  
      ),  
    );  
  }  
}

/


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий